#ifndef _list_la_h
#define _list_la_h
#include "gus2_porting.h"
/*
usage:
typedef struct StructName
{
	ListHead head; // This must be the first member
	xxxx;
	xxxx; 
}typedefName;
*/
#ifndef NULL
#define NULL 0
#endif
#define LIST_POISON1  (NULL)
#define LIST_POISON2  (NULL)

typedef struct _tagListHead
{
	struct _tagListHead* next;
	struct _tagListHead* prev;
}ListHead;

typedef ListHead ListNode;

#define INIT_LIST_HEAD(ptr) do { \
	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

#define LIST_HEAD(name) \
	ListHead name = { &name, &name }


#define LIST_PRE_NODE(ptr) (ptr)->prev

static INLINE void __list_add(ListHead *pNew, ListHead *prev, ListHead *next)
{
	next->prev = pNew;
	pNew->next = next;
	pNew->prev = prev;
	prev->next = pNew;
}

static INLINE void list_add(ListHead *pNew, ListHead *head)
{
	__list_add(pNew, head, head->next);
}

static INLINE void list_add_tail(ListHead *pNew, ListHead *head)
{
	__list_add(pNew, head->prev, head);
}
#define list_entry(ptr) \
	(void*) (ptr)

#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); \
        	pos = pos->next)

#define list_for_each_prev(pos, head)\
	for (pos = (head)->prev; pos != (head); \
        	pos = pos->prev)

static INLINE void __list_del(ListHead * prev, ListHead * next)
{
	next->prev = prev;
	prev->next = next;
}

static INLINE void list_del(void *node)
{
	ListHead *entry = (ListHead*)node;
	__list_del(entry->prev, entry->next);
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
}
static INLINE void list_del_init(ListHead *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}
/*
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static INLINE void list_move(ListHead *list, ListHead *head)
{
	__list_del(list->prev, list->next);
	list_add(list, head);
}
/*
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static INLINE void list_move_tail(ListHead *list, ListHead *head)
{
	__list_del(list->prev, list->next);
	list_add_tail(list, head);
}

/*
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static INLINE int list_empty(const ListHead *head)
{
	return head->next == head;
}
static INLINE void __list_splice(ListHead *list,
	ListHead *head)
{
	ListHead *first = list->next;
	ListHead *last = list->prev;
	ListHead *at = head->next;

	first->prev = head;
	head->next = first;

	last->next = at;
	at->prev = last;
}

/*
 * list_splice - join two lists
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static INLINE void list_splice(ListHead *list, ListHead *head)
{
	if (!list_empty(list))
		__list_splice(list, head);
}

/*
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static INLINE void list_splice_init(ListHead *list, ListHead *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head);
		INIT_LIST_HEAD(list);
	}
}

static ListHead* pop_head(ListHead* head)
{
	ListHead* node = head->next;
	list_del(node);
	return node;
}
static ListHead* list_pop_tail(ListHead* head)
{
	ListHead* node = head->prev;
	list_del(node);
	return node;
}
static void list_push_haed(ListHead* head, ListNode* node)
{
	list_add(node, head);
}
static void list_push_tail(ListHead* head, ListNode* node)
{
	list_add_tail(node, head);
}
typedef int(*list_find_cmp_fnt)(const ListNode* node, unsigned int data);
// if equal return 0
// if found return node else return NULL
static ListNode* list_find(const ListHead* head, unsigned int data, list_find_cmp_fnt cmper)
{
	ListNode* node = NULL;
	if (list_empty(head))
	{
		return NULL;
	}
	list_for_each(node, head)
	{
		if (cmper(node, data) == 0)
		{
			return node;
		}
	}
	return NULL;
}
#endif
